import { director, EventTarget, game, Game, profiler } from 'cc';
import { Arrays, Global, Logger, Objects } from '../../../../wing/assets/src';
import type { Environment } from '../declarations';
import { AudioPlayer, LocalStore, ResLoader, Stage } from '../manager';
import { View } from './View';

/** 应用状态 */
type ApplicationStatus = 'none' | 'inited' | 'running' | 'paused' | 'stopped' | 'detached';

/**
 * - 作者: DoooReyn
 * - 日期: 2023.10.30
 * - 名称: Application
 * - 描述: 应用
 */
export class Application extends EventTarget {
    /** 事件类型 */
    public static readonly EventType = {
        /** 应用初始化完成 */
        Inited: 'inited',
        /** 应用运行 */
        Running: 'running',
        /** 应用暂停 */
        Paused: 'paused',
        /** 应用恢复 */
        Resumed: 'resumed',
        /** 应用停止 */
        Stopped: 'stopped',
        /** 应用退出 */
        Detached: 'detached',
        /** 应用进入前台 */
        EnterForeground: 'enter-foreground',
        /** 应用进入后台 */
        EnterBackground: 'enter-background',
        /** 内存警告 */
        LowMemory: 'low-memory',
    } as const;

    /** 当前状态 */
    private __status: ApplicationStatus = 'none';

    /** 临时状态 */
    private __temporary: boolean = false;

    /** 活跃应用组件 */
    private __activity: View | null = null;

    /** 视图 */
    public view: View;

    /** 舞台 */
    public stage: Stage;

    /** 环境配置 */
    public environment: Environment;

    /** 资源加载器单例 */
    public resLoader: ResLoader;

    /** 音频播放器单例 */
    public audioPlayer: AudioPlayer;

    /** 本地存储管理器案例 */
    public localStore: LocalStore;

    /** 当前状态 */
    public get status() {
        return this.__status;
    }

    /** 用户习惯本地配置 */
    public get preferences() {
        return this.localStore.get<Environment['preferences']>('preferences');
    }

    /** 日志服务 */
    public get logger() {
        return Logger.getLogger(this.uname);
    }

    /** 模块名称 */
    public get uname() {
        return 'Application';
    }

    /** 应用画布 */
    public get canvas(): HTMLCanvasElement {
        return game.canvas!;
    }

    /** 根节点 */
    public get root() {
        return this?.__activity?.node;
    }

    /** 当前场景 */
    public get scene() {
        return director.getScene();
    }

    /** 主摄像机 */
    public get mainCamera() {
        return this?.__activity?.camera;
    }

    /**
     * 应用初始化
     * @param activity 当前活跃的应用组件
     */
    public async init(activity: View, env: Environment) {
        if (this.__status === 'none' && !this.__temporary) {
            this.__temporary = true;
            this.__activity = activity;
            this.view = activity;
            this.environment = Objects.deepFreeze(env) as Environment;
            await this.onInit();
            this.__temporary = false;
            this.__status = 'inited';
            this.emit(Application.EventType.Inited);
        }
    }

    /** 应用启动 */
    public async start() {
        if (this.__status === 'inited' && !this.__temporary) {
            this.__temporary = true;
            await this.onStart();
            this.__temporary = false;
            this.__status = 'running';
            this.emit(Application.EventType.Running);
        }
    }

    /** 应用暂停 */
    public async pause() {
        if (this.__status === 'running' && !this.__temporary) {
            this.__temporary = true;
            await this.onPause();
            this.__temporary = false;
            this.__status = 'paused';
            this.emit(Application.EventType.Paused);
        }
    }

    /** 应用恢复 */
    public async resume() {
        if (this.__status === 'paused' && !this.__temporary) {
            this.__temporary = true;
            await this.onResume();
            this.__temporary = false;
            this.__status = 'running';
            this.emit(Application.EventType.Resumed);
        }
    }

    /** 应用停止 */
    public async stop() {
        if (Arrays.contains(['inited', 'running', 'paused'], this.__status) && !this.__temporary) {
            this.__temporary = true;
            await this.onStop();
            this.__temporary = false;
            this.__status = 'stopped';
            this.emit(Application.EventType.Stopped);
        }
    }

    /** 应用重置 */
    public async reset() {
        // 重置首先要停止应用
        await this.stop();
        // 然后再尝试重启（重启不需要重新初始化）
        if (Arrays.contains(['stopped', 'running', 'paused'], this.__status) && !this.__temporary) {
            this.__temporary = true;
            await this.onReset();
            this.__temporary = false;
            this.__status = 'inited';
            await this.start();
        }
    }

    /** 应用退出 */
    public async quit() {
        game.end();
    }

    /** 注册事件 */
    protected registerEvent() {
        // 进入前台
        game.on(Game.EVENT_SHOW, this.onShow, this);
        // 退到后台
        game.on(Game.EVENT_HIDE, this.onHide, this);
        // 退出应用
        game.on(Game.EVENT_CLOSE, this.onQuit, this);
        // 内存不足（移动端需要处理）
        game.on(Game.EVENT_LOW_MEMORY, this.onLowMemory, this);
    }

    /** 注销事件 */
    protected unregisterEvent() {
        game.off(Game.EVENT_SHOW, this.onShow, this);
        game.off(Game.EVENT_HIDE, this.onHide, this);
        game.off(Game.EVENT_CLOSE, this.onQuit, this);
        game.off(Game.EVENT_LOW_MEMORY, this.onLowMemory, this);
    }

    /** 应用初始化时调用 */
    protected async onInit() {
        this.logger.debug('正在初始化...');
        
        // 初始化环境
        this.environment.isDevVersion && Global.mount('app', this);
        this.environment.isShowDevInfo ? profiler.showStats() : profiler.hideStats();
        game.frameRate = this.environment.fpsApsect[this.environment.fps];
        
        // 初始化资源管理器
        this.resLoader = ResLoader.GetInstance();
        await this.resLoader.init();
        this.logger.debug('资源加载器准备就绪');
        
        // 初始化本地存储管理器
        this.localStore = LocalStore.GetInstance();
        await this.localStore.init(this.environment.appName);
        this.localStore.mount<Environment['preferences']>('preferences', this.environment.preferences);
        this.logger.debug('本地存储管理器准备就绪');
        
        // 初始化音频播放器
        this.audioPlayer = AudioPlayer.GetInstance();
        await this.audioPlayer.init(this.root);
        this.logger.debug('音频播放器准备就绪');

        // 初始化视图
        await this.view.init();
        this.logger.debug('视图准备就绪');

        // 初始化舞台管理器
        this.stage = Stage.GetInstance();
        await this.stage.init();
        this.logger.debug('舞台管理器准备就绪');
        
        // 注册事件
        this.registerEvent();
    }

    /** 应用启动时调用 */
    protected async onStart() {
        this.logger.debug('正在启动...');
        await this.stage.enter(this.environment.stage);
    }

    /** 应用暂停时调用 */
    protected async onPause() {
        this.logger.debug('暂停');
        this.audioPlayer.pause();
    }

    /** 应用恢复时调用 */
    protected async onResume() {
        this.logger.debug('恢复');
        this.audioPlayer.resume();
    }

    /** 应用停止时调用 */
    protected async onStop() {
        this.logger.debug('停止');
        this.audioPlayer.stop();
        // 停止意味着退出当前舞台
        await this.stage.exit();
    }

    /** 应用重置时调用 */
    protected async onReset() {
        this.logger.debug('重置');
        this.audioPlayer.stop();
    }

    /** 应用退出时调用 */
    protected async onQuit() {
        this.logger.debug('退出');
        this.__status = 'detached';
        this.__activity = null;
        this.unregisterEvent();
        this.emit(Application.EventType.Detached);
    }

    /** 回到前台时调用 */
    protected async onShow() {
        this.logger.debug('进入前台');
        this.emit(Application.EventType.EnterForeground);
    }

    /** 进入后台时调用 */
    protected async onHide() {
        this.logger.debug('退到后台');
        this.emit(Application.EventType.EnterBackground);
    }

    /** 内存不足时调用 */
    protected async onLowMemory(): Promise<void> {
        this.logger.debug('内存警告');
        this.emit(Application.EventType.LowMemory);
    }
}

/** 当前应用 */
export const app = new Application();
